package com.glzn.springboot03.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.glzn.springboot03.entity.RealData;
import com.glzn.springboot03.mapper.RealDataMapper;
import com.glzn.springboot03.mqtt.MqttPublishClient;
import com.glzn.springboot03.service.RealDataService;
import com.glzn.springboot03.util.ComService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Lenovo
 */
@Service
public class RealDataServiceImpl implements RealDataService {
	private final static Logger logger = LoggerFactory.getLogger(EventServiceImpl.class);

	private Map<String, Integer> map = new HashMap<>();

	@Autowired
	RealDataMapper realDataMapper;

	@Override
	public String listRealData() throws UnsupportedEncodingException {
		HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
		MqttPublishClient mqttPublishClient = (MqttPublishClient) session.getAttribute("mqttPublishClient");
		Integer deviceId = (Integer) session.getAttribute("device_id");
		String sessionId = session.getId();

		if (mqttPublishClient == null) {
			return "device";
		}
		//1、获取数据
		int process = 0;

		ComService comService = new ComService();
		comService.setServerType(0x4);
		comService.setCmd(0x50);

		byte[] data = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
		if(null == data){
			return "failed";
		}
		//3、将数据组成Event List
		List<RealData> realDataList =  new ArrayList<>();
		int nPos = 7;
		int realDataCount = (data[nPos + 1] & 0xFF) << 8 | data[nPos] & 0xFF;
		nPos += 2;
		//计数器
		int count = 0;
		while (true) {
			int curCount = data[nPos++];
			for (int i = 0; i < curCount; i++) {
				//key
				int key = (data[nPos + 1] & 0xFF) << 8 | data[nPos] & 0xFF;
				nPos+=2;
				//类型
				int len = 18;
				String type = new String(data, nPos, len, "gbk");
				type = type.replaceAll("\u0000","");
				logger.debug("type:{}", type);
				nPos += len;
				//名称
				len = 32;
				String name = new String(data, nPos, len - 1, "gbk");
				name = name.replaceAll("\u0000","");
				logger.debug("name:{}", name);
				nPos += len;
				//值
				len = 16;
				String value = new String(data, nPos, len-1, "gbk");
				value = value.replaceAll("\u0000","");
				logger.debug("value:{}", value);
				nPos += len;
				//扩展
				len = 16;
				String extend = new String(data, nPos, len-1, "gbk");
				extend = extend.replaceAll("\u0000","");
				logger.debug("extend:{}", extend);
				nPos += len;

				RealData realData = new RealData(key, type, name, value, extend, deviceId);
				realDataList.add(realData);
				//进度
				count++;
				process = 100*count/realDataCount;
				map.put(sessionId, process);
			}
			if (count < realDataCount) {
				//重新获取数据
				comService.setServerType(0x4);
				comService.setCmd(0x50);

				data = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
				int errTimes = 0;
				while (data == null) {
					data = mqttPublishClient.sendAndRecv(comService, 1000 * 20, true);
					errTimes++;
					if(errTimes > 3) {
						return "failed";
					}
				}
				nPos = 9;
			} else {
				break;
			}
		}

		//2、删除原来的数据
		deleteAll(deviceId);

		//3、保存新的数据
		for (RealData realData : realDataList) {
			insert(realData);
		}
		process = 100;
		map.put(sessionId, process);
		//5、返回结果
		return "success";
	}

	@Override
	public int getProcess(String sessionId) {
		Integer process = map.get(sessionId);
		if (process == null){
			process = 0;
		}
		if(process == 100) {
			map.remove(sessionId);
		}
		return process;
	}

	@Override
	public List<RealData> findAll(Integer deviceId) {
		return realDataMapper.findAll(deviceId);
	}

	@Override
	public PageInfo<RealData> findAll(int pageNum, int pageSize, Integer deviceId) {
		Page<RealData> page = PageHelper.startPage(pageNum, pageSize);
		realDataMapper.findAll(deviceId);
		return new PageInfo<>(page);
	}

	@Override
	public Boolean insert(RealData realData) {
		return realDataMapper.insert(realData);
	}

	@Override
	public boolean deleteAll(Integer deviceId) {
		return realDataMapper.deleteAll(deviceId);
	}

	@Override
	public List<RealData> findByType(String realDataType, Integer deviceId) {
		return realDataMapper.findByType(realDataType, deviceId);
	}

	@Override
	public PageInfo<RealData> findByType(String realDataType, int pageNum, int pageSize, Integer deviceId) {
		Page<RealData> page = PageHelper.startPage(pageNum, pageSize);
		realDataMapper.findByType(realDataType, deviceId);
		return new PageInfo<>(page);
	}
}
